package com.neborosoft.lib.collections;

import com.neborosoft.lib.API_8.Collections;
import com.neborosoft.lib.collections.stack.Stack;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: CM
 * Date: 12.01.13
 * Time: 6:00
 * To change this template use File | Settings | File Templates.
 */
public class RewritableFixedSizeCollection<T> implements Stack<T> {
    private Collection<T> collection;
    private int maxSize;
    private int size;

    public Collection<T> getCollection() {
        return Collections.unmodifiableCollection(collection);
    }

    public int getMaxSize() {
        return maxSize;
    }

    public int getSize() {
        return size;
    }

    public RewritableFixedSizeCollection(Collection<T> collection, int maxSize) {
        if (maxSize <= 0) {
            throw new IllegalArgumentException();
        }

        this.collection = collection;
        this.maxSize = maxSize;
    }

    private void addSize(T object){
        size += sizeOf(object);

        while(size > maxSize){
            Iterator<T> iterator = collection.iterator();
            T evictedObject = iterator.next();
            onEvicted(evictedObject);
            size -= sizeOf(evictedObject);
            iterator.remove();
        }
    }

    private void checkSize(T object){
        if(!canBePlaced(object)) {
            throw new IllegalArgumentException();
        }
    }

    public boolean add(T object){
        checkSize(object);

        if(!collection.add(object)) {
            return false;
        }

        addSize(object);
        return true;
    }

    public boolean remove(T object) {
        if(collection.remove(object)) {
            size -= sizeOf(object);
            return true;
        }
        return false;
    }

    public final boolean canBePlaced(T object){
        return sizeOf(object) <= maxSize;
    }

    public int sizeOf(T object){
        return 1;
    }

    @Override
    public boolean isEmpty(){
        return size <= 0;
    }

    @Override
    public void push(T value) {
        add(value);
    }

    @Override
    public T pop() {
        if(collection instanceof List){
            List<T> list = (List<T>)collection;
            return list.remove(list.size() - 1);
        } else {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public T top() {
        return null;
    }

    public boolean isFull(){
        return maxSize == size;
    }

    protected void onEvicted(T object){

    }
}
